package com.inno.game.server;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


import com.inno.game.handler.SocketHandler;
import com.inno.game.util.SpringHelper;
import com.sun.org.apache.bcel.internal.generic.NEW;


public class GameServer{

	/**
	 * 
	 */
	private static String encoding = "GBK";

	private static final long serialVersionUID = 2706343257330041717L;
	ThreadPoolExecutor threadPool = new ThreadPoolExecutor(20, 30, 3, TimeUnit. SECONDS ,
			new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardOldestPolicy() );
	public static void main(String[] args) throws IOException, Exception{
		loadSpring();
		(new GameServer()).start();
	}
	private final int POOL_SIZE=10;//单个CPU线程池大小
	public synchronized void start(){
		ServerSocket ss = null;
		ExecutorService executorService=Executors.newFixedThreadPool(
				Runtime.getRuntime().availableProcessors()*POOL_SIZE);
		try {
			ss = new ServerSocket(8080);
			System.out.println("Start...");
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		while(true) {
			try {
				Socket client=null;//客户Socket
				int contentLength = 0;// 客户端发送的 HTTP 请求的主体的长度
				client=ss.accept();
				System.out.println(client.toString());
//				Runnable run = new SocketHandler(client);
				
				SocketHandler run = SpringHelper.getBean("SocketHandler");
				run.setClient(client);
				threadPool.execute(run);
			}
			catch (Exception e) {
				System.err.println(e);
			}
		}
	}
	public static void loadSpring() {
		SpringHelper.initApplicationContext();
	}
	public static String getMsg(Socket s, String content) throws Exception, IOException{
		//59.108.115.101 : 7888
//		if (s.isClosed()) {
//			s = new Socket("59.108.115.101", 7888);
//		}
		System.out.println(s.toString());
		OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
		osw.write(content);
		osw.flush();
		//		osw.close();
		InputStream is = s.getInputStream();
		//			BufferedReader reader = new BufferedReader(is);
		BufferedInputStream bis = new BufferedInputStream(is);
		//			bis.read()
		InputStreamReader isr2 = new InputStreamReader(is);
		BufferedReader reader2 = new BufferedReader(isr2);
		StringBuffer sBuffer2 = new StringBuffer();
		String line2 = "";
		while (!("\r\n").equals(line2 = readLine(is, 0))){
			sBuffer2.append(line2+"\r\n");
			//			System.out.println(line2);
		}
		//		isr2
		//		is.close();
		reader2.close();
		//		s.close();
		return sBuffer2.append("\r\n").toString();
	}

	/*
	 * 这里我们自己模拟读取一行，因为如果使用API中的BufferedReader时，它是读取到一个回车换行后
	 * 才返回，否则如果没有读取，则一直阻塞，直接服务器超时自动关闭为止，如果此时还使用BufferedReader
	 * 来读时，因为读到最后一行时，最后一行后不会有回车换行符，所以就会等待。如果使用服务器发送回来的
	 * 消息头里的Content-Length来截取消息体，这样就不会阻塞
	 * 
	 * contentLe 参数 如果为0时，表示读头，读时我们还是一行一行的返回；如果不为0，表示读消息体，
	 * 时我们根据消息体的长度来读完消息体后，客户端自动关闭流，这样不用先到服务器超时来关闭。
	 */
	private static String readLine(InputStream is, int contentLe) throws IOException {
		ArrayList lineByteList = new ArrayList();
		byte readByte;
		int total = 0;
		if (contentLe != 0) {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
				total++;
			} while (total < contentLe);//消息体读还未读完
		} else {
			do {
				readByte = (byte) is.read();
				lineByteList.add(Byte.valueOf(readByte));
			} while (readByte != 10);
		}

		byte[] tmpByteArr = new byte[lineByteList.size()];
		for (int i = 0; i < lineByteList.size(); i++) {
			tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
		}
		lineByteList.clear();

		return new String(tmpByteArr, encoding);
	}
}
